const cron = require('node-cron');
const logger = require('../utils/logger');
const internalService = require('./internalService');
const externalApi = require('./externalApi');
const { dataSync } = require('../config/schedulerConfig');

class SchedulerService {
  constructor() {
    this.tasks = new Map();
    this.isRunning = false;
    this.initDefaultTasks();
  }

  /**
   * 初始化默认定时任务
   */
  initDefaultTasks() {
    // 数据同步任务 - 每小时执行一次
    this.addTask('dataSync', dataSync.schedule, async () => {
      try {
        // 获取当前执行时间（整点时间）
        const now = new Date();
        const cycleTime = this.formatCycleTime(now);
        
        await internalService.executeTask('dataSync', {
          tables: ['stocks', 'news', 'market_data'],
          incremental: true,
          cycleTime: cycleTime // 传递整点时间
        });
        // logger.info('定时数据同步任务完成');
      } catch (error) {
        logger.error('定时数据同步任务失败', { error: error.message });
      }
    });
  }

  /**
   * 格式化周期时间为整点时间
   * @param {Date} date - 日期对象
   * @returns {string} 格式化的时间字符串
   */
  formatCycleTime(date) {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hour = String(date.getHours()).padStart(2, '0');
    const minute = String(date.getMinutes()).padStart(2, '0');
    const second = String(date.getSeconds()).padStart(2, '0');
    return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
  }

  /**
   * 添加定时任务
   * @param {string} name - 任务名称
   * @param {string} schedule - cron表达式
   * @param {function} task - 任务函数
   * @param {object} options - 任务选项
   * @returns {boolean} 是否添加成功
   */
  addTask(name, schedule, task, options = {}) {
    try {
      if (this.tasks.has(name)) {
        logger.warn(`定时任务 ${name} 已存在，将被覆盖`);
        this.removeTask(name);
      }

      // 验证cron表达式
      if (!cron.validate(schedule)) {
        logger.error(`无效的cron表达式: ${schedule}`);
        return false;
      }

      const cronTask = cron.schedule(schedule, task, {
        scheduled: false,
        timezone: options.timezone || 'Asia/Shanghai',
        ...options
      });

      this.tasks.set(name, {
        cronTask,
        schedule,
        task,
        options,
        isRunning: false,
        lastRun: null,
        nextRun: this.calculateNextRun(schedule),
        runCount: 0,
        errorCount: 0
      });
      return true;
    } catch (error) {
      logger.error(`添加定时任务 ${name} 失败`, { error: error.message });
      return false;
    }
  }

  /**
   * 移除定时任务
   * @param {string} name - 任务名称
   * @returns {boolean} 是否移除成功
   */
  removeTask(name) {
    try {
      const taskInfo = this.tasks.get(name);
      if (!taskInfo) {
        logger.warn(`定时任务 ${name} 不存在`);
        return false;
      }

      taskInfo.cronTask.stop();
      this.tasks.delete(name);
      logger.info(`定时任务 ${name} 移除成功`);
      return true;
    } catch (error) {
      logger.error(`移除定时任务 ${name} 失败`, { error: error.message });
      return false;
    }
  }

  /**
   * 启动定时任务
   * @param {string} name - 任务名称，如果不指定则启动所有任务
   * @returns {boolean} 是否启动成功
   */
  startTask(name = null) {
    try {
      if (name) {
        return this.startSingleTask(name);
      } else {
        return this.startAllTasks();
      }
    } catch (error) {
      logger.error('启动定时任务失败', { error: error.message });
      return false;
    }
  }

  /**
   * 启动单个定时任务
   * @param {string} name - 任务名称
   * @returns {boolean} 是否启动成功
   */
  startSingleTask(name) {
    try {
      const taskInfo = this.tasks.get(name);
      if (!taskInfo) {
        logger.warn(`定时任务 ${name} 不存在`);
        return false;
      }

      if (taskInfo.isRunning) {
        logger.warn(`定时任务 ${name} 已在运行中`);
        return true;
      }

      taskInfo.cronTask.start();
      taskInfo.isRunning = true;
      
      try {
        taskInfo.nextRun = this.calculateNextRun(taskInfo.schedule);
      } catch (calcError) {
        logger.warn(`定时任务 ${name} 下次运行时间计算失败，使用默认值`, { error: calcError.message });
        const nextRun = new Date();
        nextRun.setHours(nextRun.getHours() + 1);
        taskInfo.nextRun = nextRun;
      }
      return true;
    } catch (error) {
      logger.error(`启动定时任务 ${name} 失败`, { error: error.message });
      return false;
    }
  }

  /**
   * 启动所有定时任务
   * @returns {boolean} 是否启动成功
   */
  startAllTasks() {
    try {
      let successCount = 0;
      let totalCount = this.tasks.size;

      for (const [name, taskInfo] of this.tasks) {
        if (this.startSingleTask(name)) {
          successCount++;
        }
      }

      this.isRunning = successCount > 0;
      logger.info(`定时任务启动完成`, { successCount, totalCount });
      return successCount === totalCount;
    } catch (error) {
      logger.error('启动所有定时任务失败', { error: error.message });
      return false;
    }
  }

  /**
   * 停止定时任务
   * @param {string} name - 任务名称，如果不指定则停止所有任务
   * @returns {boolean} 是否停止成功
   */
  stopTask(name = null) {
    try {
      if (name) {
        return this.stopSingleTask(name);
      } else {
        return this.stopAllTasks();
      }
    } catch (error) {
      logger.error('停止定时任务失败', { error: error.message });
      return false;
    }
  }

  /**
   * 停止单个定时任务
   * @param {string} name - 任务名称
   * @returns {boolean} 是否停止成功
   */
  stopSingleTask(name) {
    try {
      const taskInfo = this.tasks.get(name);
      if (!taskInfo) {
        logger.warn(`定时任务 ${name} 不存在`);
        return false;
      }

      if (!taskInfo.isRunning) {
        logger.warn(`定时任务 ${name} 未在运行`);
        return true;
      }

      taskInfo.cronTask.stop();
      taskInfo.isRunning = false;

      logger.info(`定时任务 ${name} 停止成功`);
      return true;
    } catch (error) {
      logger.error(`停止定时任务 ${name} 失败`, { error: error.message });
      return false;
    }
  }

  /**
   * 停止所有定时任务
   * @returns {boolean} 是否停止成功
   */
  stopAllTasks() {
    try {
      let successCount = 0;
      let totalCount = this.tasks.size;

      for (const [name, taskInfo] of this.tasks) {
        if (this.stopSingleTask(name)) {
          successCount++;
        }
      }

      this.isRunning = false;
      logger.info(`定时任务停止完成`, { successCount, totalCount });
      return successCount === totalCount;
    } catch (error) {
      logger.error('停止所有定时任务失败', { error: error.message });
      return false;
    }
  }

  /**
   * 立即执行任务
   * @param {string} name - 任务名称
   * @returns {boolean} 是否执行成功
   */
  async executeTaskNow(name) {
    try {
      const taskInfo = this.tasks.get(name);
      if (!taskInfo) {
        logger.warn(`定时任务 ${name} 不存在`);
        return false;
      }

      logger.info(`立即执行定时任务: ${name}`);
      taskInfo.lastRun = new Date();
      taskInfo.runCount++;

      try {
        await taskInfo.task();
        logger.info(`定时任务 ${name} 执行成功`);
        return true;
      } catch (error) {
        taskInfo.errorCount++;
        logger.error(`定时任务 ${name} 执行失败`, { error: error.message });
        return false;
      }
    } catch (error) {
      logger.error(`立即执行定时任务 ${name} 失败`, { error: error.message });
      return false;
    }
  }

  /**
   * 获取任务状态
   * @param {string} name - 任务名称，如果不指定则返回所有任务状态
   * @returns {object|Array} 任务状态信息
   */
  getTaskStatus(name = null) {
    try {
      if (name) {
        const taskInfo = this.tasks.get(name);
        if (!taskInfo) {
          return null;
        }
        return this.formatTaskStatus(name, taskInfo);
      } else {
        const status = [];
        for (const [taskName, taskInfo] of this.tasks) {
          status.push(this.formatTaskStatus(taskName, taskInfo));
        }
        return status;
      }
    } catch (error) {
      logger.error('获取任务状态失败', { error: error.message });
      return null;
    }
  }

  /**
   * 格式化任务状态
   * @param {string} name - 任务名称
   * @param {object} taskInfo - 任务信息
   * @returns {object} 格式化的任务状态
   */
  formatTaskStatus(name, taskInfo) {
    return {
      name,
      schedule: taskInfo.schedule,
      isRunning: taskInfo.isRunning,
      lastRun: taskInfo.lastRun,
      nextRun: taskInfo.nextRun,
      runCount: taskInfo.runCount,
      errorCount: taskInfo.errorCount,
      timezone: taskInfo.options.timezone || 'Asia/Shanghai'
    };
  }

  /**
   * 获取调度器状态
   * @returns {object} 调度器状态
   */
  getSchedulerStatus() {
    return {
      isRunning: this.isRunning,
      totalTasks: this.tasks.size,
      runningTasks: Array.from(this.tasks.values()).filter(task => task.isRunning).length,
      stoppedTasks: Array.from(this.tasks.values()).filter(task => !task.isRunning).length,
      timestamp: new Date().toISOString()
    };
  }

  /**
   * 计算下一次运行时间
   * @param {string} schedule - cron表达式
   * @returns {Date} 下一次运行时间
   */
  calculateNextRun(schedule) {
    try {
      // 使用 cron-parser 的 CronExpressionParser 类来计算下次运行时间
      const { CronExpressionParser } = require('cron-parser');
      const interval = CronExpressionParser.parse(schedule, {
        tz: 'Asia/Shanghai'
      });
      return interval.next().toDate();
    } catch (error) {
      logger.warn('无法计算下次运行时间，使用默认值', { schedule, error: error.message });
      // 如果无法解析，返回1小时后
      const nextRun = new Date();
      nextRun.setHours(nextRun.getHours() + 1);
      return nextRun;
    }
  }

  /**
   * 重启调度器
   * @returns {boolean} 是否重启成功
   */
  async restart() {
    try {
      logger.info('开始重启定时任务调度器');
      
      this.stopAllTasks();
      await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒
      this.startAllTasks();
      
      logger.info('定时任务调度器重启完成');
      return true;
    } catch (error) {
      logger.error('重启定时任务调度器失败', { error: error.message });
      return false;
    }
  }
}

module.exports = new SchedulerService();
